namespace SPDeploy.Library.Processing.Processors
{
    using System;
    using Data;
    using Exceptions;
    using Helpers;
    using Library;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    public class FeatureActivationProcessor : ProcessorBase<FeatureActivation, SPFeature>
    {
        #region Properties: public

        [ProcessorSetting(DefaultValue = IgnorableBehaviors.Ignore)]
        public IgnorableBehaviors AlreadyActivated { get; set; }

        [ProcessorSetting(DefaultValue = IgnorableBehaviors.Ignore)]
        public IgnorableBehaviors AlreadyDeactivated { get; set; }

        public override string Name
        {
            get { return "FeatureActivation"; }
        }

        #endregion

        #region Methods: public

        public override SPFeature Install(ProcessorContext ctx, FeatureActivation config)
        {
            Log(LogSeverity.Step, "Activating feature with guid {0} ({1})", config.Guid, config.Description);
            SPFeatureCollection targetCollection = GetTargetCollection(ctx, config);
            var featureGuid = new Guid(config.Guid);
            if (targetCollection[featureGuid] != null)
            {
                if (AlreadyActivated == IgnorableBehaviors.Ignore)
                {
                    Log(LogSeverity.SubStep, "Feature already activated - config instructed ignoring it");
                    return targetCollection[featureGuid];
                }
                else
                {
                    throw new DeploymentTargetConfigException("A Feature with the guid " + config.Guid + " has already been activated");
                }
            }
            return targetCollection.Add(featureGuid);
        }

        public override SPFeature Uninstall(ProcessorContext ctx, FeatureActivation config)
        {
            Log(LogSeverity.Step, "Deactivating feature with guid {0} ({1})", config.Guid, config.Description);
            SPFeatureCollection targetCollection = GetTargetCollection(ctx, config);
            var featureGuid = new Guid(config.Guid);
            if (targetCollection[featureGuid] == null)
            {
                if (AlreadyDeactivated == IgnorableBehaviors.Ignore)
                {
                    Log(LogSeverity.SubStep, "Feature not activated - config instructed ignoring it");
                    ctx.ChildrenDeleted = true;
                    return null;
                }
                else
                {
                    throw new DeploymentTargetConfigException("A Feature with the guid " + config.Guid + " could not be found (and thus deactivated)");
                }
            }
            targetCollection.Remove(featureGuid);
            ctx.ChildrenDeleted = true;
            return null;
        }

        public override SPFeature Update(ProcessorContext ctx, FeatureActivation oldConfig, FeatureActivation newConfig)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Methods: private

        private SPFeatureCollection GetTargetCollection(ProcessorContext context, FeatureActivation config)
        {
            if (context.ParentResult == null)
            {
                throw new DeploymentTargetProcessorException("FeatureActivationProcessor processor (" + config.Guid + ") did not receive a valid parent instance");
            }
            if (context.ParentResult is SPWebApplication)
            {
                var webApp = context.ParentResult as SPWebApplication;
                Log(LogSeverity.SubStep, "Target web application is {0}", webApp.Name);
                return webApp.Features;
            }
            if (context.ParentResult is SPSite)
            {
                var site = context.ParentResult as SPSite;
                Log(LogSeverity.SubStep, "Target site is {0}", site.Url);
                return site.Features;
            }
            if (context.ParentResult is SPWeb)
            {
                var web = context.ParentResult as SPWeb;
                Log(LogSeverity.SubStep, "Target web is {0}", web.Url);
                return web.Features;
            }
            throw new DeploymentTargetProcessorException("FeatureActivationProcessor processor (" + config.Guid + ") did not receive a valid parent type");
        }

        #endregion
    }
}